#ifndef __M_TCP_H__
#define __M_TCP_H__
#include<iostream>
#include<string>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<unistd.h>
#include<signal.h>

class TcpSocket{
    private:
        int _sockfd;
    public:
    TcpSocket():_sockfd(-1){}
    TcpSocket(int fd):_sockfd(fd){}
    int FD(){return _sockfd;}
    void reuseAddr(){
        int opt = 1;
        setsockopt(_sockfd,SOL_SOCKET,SO_REUSEADDR,(void*)&opt,sizeof(opt));
        opt = 1;
        setsockopt(_sockfd,SOL_SOCKET,SO_REUSEPORT,(void*)&opt,sizeof(opt));
    }
    bool createServer(int port){
        _sockfd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
        if(_sockfd<0){
            perror("socket error");
            return false;
        }
        struct sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_port = htons(port);
        addr.sin_addr.s_addr = INADDR_ANY;
        socklen_t len = sizeof(struct sockaddr_in);
        int ret = bind(_sockfd,(sockaddr*)&addr,len);
        if(ret<0){
            perror("bind error");
            Close();
            return false;
        }
        ret = listen(_sockfd,5);
        if(ret<0){
            perror("listen error");
            Close();
            return false;
        }
        return true;
    }
    bool createClient(int port){
        _sockfd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
        if(_sockfd<0){
            perror("socket error");
            return false;
        }
        struct sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_port = htons(port);
        addr.sin_addr.s_addr = INADDR_ANY;
        socklen_t len = sizeof(struct sockaddr_in);
        int ret = connect(_sockfd,(sockaddr*)&addr,len);
        if(ret<0){
            perror("connect error");
            Close();
            return false;
        }
        return true;
    }
    bool Accept(TcpSocket &sock){
        int newfd = accept(_sockfd,NULL,0);
        if(newfd<0){
            perror("accept error");
            return false;
        }
        sock._sockfd = newfd;
        return true;
    }
    bool Recv(std::string &body){
        body.resize(65535);
        int ret = recv(_sockfd,&body[0],65535,0);
        if(ret<0){
            perror("recv error");
            return false;
        }
        body.resize(ret);
        return true;
    }
    bool Send(const std::string &body){
        int ret = send(_sockfd,&body[0],body.size(),0);
        if(ret<=0){
            perror("send error");
            return false;
        }
        return true;
    }
    bool Close(){
            if(_sockfd<0){
                return false;
            }
            close(_sockfd);
            _sockfd = -1;
            return true;
        }
};

class NetInit{
    public:
        NetInit(){
            signal(SIGPIPE,SIG_IGN);
        }
};
static NetInit g_init;

#endif